package eu.smoothit.sis.controller.iop.impl;

import java.util.Observable;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

import org.apache.log4j.Logger;

import eu.smoothit.sis.controller.iop.DBTimer;
import eu.smoothit.sis.db.SISDBObserver;
import eu.smoothit.sis.db.SisDAOFactory;
import eu.smoothit.sis.db.api.daos.IClientSwarmInfoDAO;
import eu.smoothit.sis.db.api.daos.IComponentConfigDAO;
import eu.smoothit.sis.db.impl.entities.ComponentConfigEntry;
import eu.smoothit.sis.db.impl.utils.DBNotifyMessage;
import eu.smoothit.sis.db.impl.utils.SISDBNotifier;
import eu.smoothit.sis.init.web.SisWebInitializer;

@Stateless
public class DBTimerImpl implements DBTimer, SISDBObserver {
	private @Resource TimerService timer;
	
	/**
	 * The logger.
	 */
	private static org.apache.log4j.Logger log = Logger
			.getLogger(DBTimerImpl.class.getName());
	
	private int t_age = 0;
	private int default_t_out = 60000; //TODO after tests get the default value to around 30 mins
	public static final int default_t_age = 1800000; // 30 mins
	public static final int initTime = 150000; // 2.5 mins
	
	@Override
	@TransactionAttribute(TransactionAttributeType.SUPPORTS)
	public void startTimer() {

		//try {
		//Thread.sleep(60000);
		//} catch (Exception e) {}
		
		for (Object o : this.timer.getTimers())
			if (((Timer) o).getInfo().toString().equals("DBTimer"))
				((Timer)o).cancel();

		SisDAOFactory factory = SisDAOFactory.getFactory();
		
		SISDBNotifier notifier = factory.createSISDBNotifier();
		notifier.addObserver(this);
		
		IComponentConfigDAO dao = factory.createComponentConfigDAO();
		ComponentConfigEntry config = dao.findByComponentAndName(SisWebInitializer.COMPONENT_NAME_CONTR_IOP, SisWebInitializer.PARAM_IOP_CONTROLLER_T_OUT);
		
		if(config != null && config.getValue() != null && config.getValue() instanceof Integer)
			timer.createTimer(initTime, ((Integer) config.getValue()).longValue(), "DBTimer");
		else 
			timer.createTimer(initTime, default_t_out, "DBTimer");
		
		config = dao.findByComponentAndName(SisWebInitializer.COMPONENT_NAME_CONTR_IOP, SisWebInitializer.PARAM_IOP_CONTROLLER_T_AGE);
		
		if(config != null && config.getValue() != null && config.getValue() instanceof Integer)
			this.t_age = ((Integer) config.getValue()).intValue();
		else 
			this.t_age = default_t_age;  
		
		java.util.Date now = new java.util.Date();
		log.info(" Timer started at " + now.toString());

	}
	
	@Timeout
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void timeoutHandler(Timer timer) {
		
		if (timer.getInfo().toString().equals("DBTimer")){
			SisDAOFactory factory = SisDAOFactory.getFactory();
			IClientSwarmInfoDAO dao = factory.createClientSwarmInfoDAO();
		
			java.util.Date now = new java.util.Date();
			long aged = now.getTime() - ((Integer)this.t_age).longValue();
		
			dao.deleteSwarmsOlderThen(aged);
								
			log.info(" Timer expired at " + now.toString());
		}
	}
	
	@Override
	public void stopTimer() {
		for (Object o : this.timer.getTimers())
			if (((Timer) o).getInfo().toString().equals("DBTimer")){
				((Timer)o).cancel();
			}
	}
	
	@Override
    public void update(Observable arg0, Object arg1) {
        DBNotifyMessage result = (DBNotifyMessage) arg1;
      
        if (result.getSource().equals("ComponentConfigEntry"))
        	if (result.getAction().toString().equals("UPDATE") || result.getAction().toString().equals("PERSIST")) {
        		for (Object o : this.timer.getTimers())
        			if (((Timer) o).getInfo().toString().equals("DBTimer"))
        				((Timer)o).cancel();
        		
        		SisDAOFactory factory = SisDAOFactory.getFactory();
        		IComponentConfigDAO dao = factory.createComponentConfigDAO();
        		ComponentConfigEntry config = dao.findByComponentAndName(SisWebInitializer.COMPONENT_NAME_CONTR_IOP, SisWebInitializer.PARAM_IOP_CONTROLLER_T_OUT);
        				
        		if(config != null && config.getValue() != null && config.getValue() instanceof Integer)
        			this.timer.createTimer(((Integer) config.getValue()).longValue(), ((Integer) config.getValue()).longValue(), "DBTimer");
        		else 
        			this.timer.createTimer(default_t_out, default_t_out, "DBTimer");
        			
        		config = dao.findByComponentAndName(SisWebInitializer.COMPONENT_NAME_CONTR_IOP, SisWebInitializer.PARAM_IOP_CONTROLLER_T_AGE);
        			
        		if(config != null && config.getValue() != null && config.getValue() instanceof Integer)
        			this.t_age = ((Integer) config.getValue()).intValue();
        		else 
        			this.t_age = default_t_age;
        					
        	}
	}

}
